package udpInvoker.main;

import udpInvoker.main.lib.Invokable;
import udpInvoker.main.lib.TopicSubscriber;

import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: esr
 * Date: 20.nov.2008
 * Time: 17:03:01
 * Copyright 2008  Espen Skjervold, FFI
 */
public class SubscriptionHandler extends Invokable {

    private static SubscriptionHandler instance;
    private String publishSubscribePassword;

    private HashMap<String, ArrayList> subscriptionHash;



    public static SubscriptionHandler getInstance() {
        if (instance==null)
            instance = new SubscriptionHandler();

        return instance;


    }

    public SubscriptionHandler() {
        subscriptionHash = new HashMap();

        Thread notifierThread = new Thread(this);
        notifierThread.start();
    }

    public void setPublishSubscribePassword(String passord) {
        publishSubscribePassword = passord;
        setPassword(passord);
    }

    public void addSubscription(String topic, TopicSubscriber topicSubscriber) {

        topic = topic.toUpperCase();


        if (!subscriptionHash.containsKey(topic))
            subscriptionHash.put(topic, new ArrayList());

        ArrayList subscribers = subscriptionHash.get(topic);

        subscribers.add(topicSubscriber);



    }

    public void removeSubscription(String topic, TopicSubscriber topicSubscriber) {

        topic = topic.toUpperCase();

        if (subscriptionHash.containsKey(topic)) {
            ArrayList subscribers = subscriptionHash.get(topic);
            if (subscribers.contains(topicSubscriber))
                subscribers.remove(topicSubscriber);
        }
    }


    public void xxDeliverPublishedMessage(String topic, SubscriptionMessage subscriptionMessage) {

        topic = topic.toUpperCase();

        ArrayList relevantTopicsLists = getRelevantTopicLists(topic);  //hierarchical topics. e.g ffi.news.international matches ffi.news
        
        for (int i=0;i<relevantTopicsLists.size();i++) {
            ArrayList subscribers = (ArrayList) relevantTopicsLists.get(i);
            notifyTopicSubscribers(topic, subscriptionMessage, subscribers);
        }


    }

    private ArrayList getRelevantTopicLists(String topic) {
        //get all topics higher in the hierarchy. E.g ffi.new.int also returns ffi.news

        ArrayList relevantTopicLists = new ArrayList();

        Iterator topics = subscriptionHash.keySet().iterator();
        while (topics.hasNext()) {
            String tempTopic = (String) topics.next();
            if (tempTopic.equals(topic) ||  topic.startsWith(tempTopic + "."))
                relevantTopicLists.add(subscriptionHash.get(tempTopic));
        }

        return relevantTopicLists;
    }

    private void notifyTopicSubscribers(String topic, SubscriptionMessage subscriptionMessage, ArrayList subscribers) {
        for (int i=0;i<subscribers.size();i++) {
            TopicSubscriber topicSubscriber = (TopicSubscriber) subscribers.get(i);
            try {
                topicSubscriber.deliverMessage(topic, subscriptionMessage.getPayload());
            } catch (Exception e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
    }

}
